package classifiers;

import draw.ExploringMedics;
import java.util.LinkedList;

public class PerimetrClassifier extends AbstractDoAction {

    public PerimetrClassifier(int[][] regionsOfInterest) {
        super(regionsOfInterest);
    }
    public int regionSize = 0;
    public int perimetr = 0;
    public int minx = Integer.MAX_VALUE;
    public int miny = Integer.MAX_VALUE;
    public int maxx = 0;
    public int maxy = 0;
    public static final int IN_COMPONENT = 875;
    public static final int CIRCLES = 130;

    public void findConnectedComponent(int xPoint, int yPoint, int oldType, int newType, boolean doCount) {

        LinkedList<Integer> xQueue = new LinkedList<Integer>();
        LinkedList<Integer> yQueue = new LinkedList<Integer>();

        xQueue.push(xPoint);
        yQueue.push(yPoint);

        int dx[] = {-1, 1, 0, 0};
        int dy[] = {0, 0, -1, 1};

        regionSize = 1;
        perimetr = 0;
        minx = Integer.MAX_VALUE;
        miny = Integer.MAX_VALUE;
        maxx = 0;
        maxy = 0;

        while (!xQueue.isEmpty()) {
            int x = xQueue.pop();
            int y = yQueue.pop();

            if (x >= width - 1 || y >= height - 1 || x <= 0 || y <= 0) {
                continue;
            }

            if (regionsOfInterest[x][y] == oldType) {
                regionsOfInterest[x][y] = newType;

                if (doCount) {
                    regionSize++;

                    boolean isEdge = false;
                    for (int i = x - 1; i <= x + 1; i++) {
                        for (int j = y - 1; j <= y + 1; j++) {
                            if (regionsOfInterest[i][j] == ExploringMedics.BLACK) {
                                isEdge = true;
                            }
                        }
                    }
                    if (isEdge) {
                        perimetr++;
                    }
                }

                minx = x < minx ? x : minx;
                miny = y < miny ? y : miny;
                maxx = x > maxx ? x : maxx;
                maxy = y > maxy ? y : maxy;

                for (int i = 0; i < 4; i++) {
                    xQueue.push(x + dx[i]);
                    yQueue.push(y + dy[i]);
                }
            }
        }
    }
    private int minWidthCriter = 0;
    private int maxWidthCriter = 0;
    private int minHeightCriter = 0;
    private int maxHeightCriter = 0;
    private int minSquareCriter = 0;
    private int maxSquareCriter = 0;
    private int minPerimDivSqCriter = 0;
    private int maxPerimDivSqCriter = 0;

    public void setExploy(int wMin, int wMax, int hMin, int hMax, int sMin, int sMax, int minDiv, int maxDiv) {
        minWidthCriter = wMin;
        maxWidthCriter = wMax;
        minHeightCriter = hMin;
        maxHeightCriter = hMax;
        minSquareCriter = sMin;
        maxSquareCriter = sMax;
        minPerimDivSqCriter = minDiv;
        maxPerimDivSqCriter = maxDiv;
    }

    public void exployAll() {
        int regionCount = 0;
        for (int i = 0; i < width; i++) {
            for (int j = 0; j < height; j++) {
                if (regionsOfInterest[i][j] == ExploringMedics.WHITE) {
                    findConnectedComponent(i, j, ExploringMedics.WHITE, IN_COMPONENT, true);

                    int perimSq = perimetr * perimetr / regionSize;

//                    System.out.println(regionSize  + "  " + maxSquareCriter);
                    if (maxx - minx > minWidthCriter
                            && maxy - miny > minHeightCriter
                            && maxx - minx < maxWidthCriter
                            && maxy - miny < maxHeightCriter
                            && regionSize > minSquareCriter
                            && regionSize < maxSquareCriter
                            && perimSq < maxPerimDivSqCriter) {
//                        System.out.println(perimSq + "  " + maxPerimDivSqCriter);
                        findConnectedComponent(i, j, IN_COMPONENT, CIRCLES, false);
                        regionCount++;
                    }
                }
            }
        }
        System.out.println("regions " + regionCount);
    }

    @Override
    public void doAction(int xStart, int yStart) {
        findConnectedComponent(xStart, yStart, ExploringMedics.WHITE, IN_COMPONENT, true);
        System.out.println(perimetr * perimetr / regionSize + "  " + (maxx - minx) + " "
                + (maxy - miny) + " " + regionSize);
        findConnectedComponent(xStart, yStart, IN_COMPONENT, ExploringMedics.WHITE, false);
    }
}
